#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
 @Author: Monox
 @Email: 627201584@qq.com
 @FileName: 框架20231029.py
 @DateTime: 2023/10/29 8:04
 @SoftWare: PyCharm
"""

"""
001
原始JSON报文
"""
# 源系统JSON报文
json_data = {
    # 主表Header
    "source_field3": "A003",
    "source_field1": "A001",
    "source_field2": "A002",
    "source_shop": "shop001",
    "source_warehouse": "1001",
    "source_key": 123456,
    "source_time": '2023-10-29T12:12:12',
    # 明细表Details
    "source_detils": [
        {"source_item": "SP001",
         "source_qty": "2",
         "amout": "100"},
        {"source_item": "SP002",
         "source_qty": "3",
         "amout": "90"}
    ]
}

"""
002 
映射表
"""
# 主表字段映射规则
Header_mapping = {
    "source_field1": "target_field1",  # 源系统字段1：目标系统字段1
    "source_field2": "target_field2",  # 源系统字段2：目标系统字段2
    "source_field3": "target_field3",  # 源系统字段3：目标系统字段3
    u"店铺映射客户_source_shop": "target_shop",  # 根据店铺代码映射客户
    u"店铺映射组织_source_shop": "target_shopzuzhi",  # 根据店铺代码映射客户
    u"仓库映射仓库_source_warehouse": "target_warehouse",  # 主表仓库代码
    u"仓库映射组织_source_warehouse": "target_warehousezuzhi",  # 主表仓库代码
    u"重复_source_field1": "target_field4",  # 重复源系统字段1：新目标系统字段4
    u"常量_X001": "target_field5",  # 映射源系统没有的字段，将目标系统字段指定为常量
    "source_key": "target_key#str#",  # 修改目标字段格式str类型
    "source_field999": "target_field999",  # 该映射字段不在源系统报文，会返回中文提示
    "source_time": "target_time#yyyy-mm-dd#"  # 映射的同时把时间格式转换为yyyy-mm-dd
    # 添加更多的映射规则...
}

# 指定商品明细头
Details_designate = [
    # 原系统商品明细头，目标系统商品明细头
    "source_detils", "target_detils"
]

# 商品明细表字段映射规则
Details_mapping = {
    "source_item": "target_item",  # 源系统商品字段：目标系统商品字段shop
    "source_qty": "target_qty#int#",  # 源系统数量字段：目标系统数量字段
    u"重复_source_item": "target_item2",  # 重复源系统商品字段：新目标系统商品字段2
    u"常量_X002": "target_field10",  # 映射源系统没有的字段，将目标系统字段指定为常量
    u"源主表_source_warehouse": "target_warehouse",  # 主表的仓库代码映射明细表的仓库代码
    u"主表仓库映射仓库_source_warehouse": "target_warehouse2",  # 主表的仓库代码映射明细表的仓库代码
    u"主表仓库映射组织_source_warehouse": "target_warehouse_org",  # 主表的仓库代码映射明细表的仓库代码
    u"单位_source_item": "target_units",  # 根据商品代码找到财务系统的单位
    u"算单价_(amout/source_qty)": "target_price"
    # 添加更多的映射规则...
}

mapping_list = [Header_mapping, Details_designate, Details_mapping]

"""
003 
单位存库
"""
item_units_list = [
    {"identity": "SP001", "unit_id": "1", u"unit_name": u"台"},
    {"identity": "SP002", "unit_id": "2", u"unit_name": u"个"},
    {"identity": "SP003", "unit_id": "3", u"unit_name": u"包"}
]

"""
004 
店铺映射表
"""
# shop_list = {源系统店铺代码，目标系统客户代码，目标系统店铺组织代码}
shop_list = [
    {"shop_code": "shop001", "customer": "cus001", "organization": "org001"},
    {"shop_code": "shop002", "customer": "cus002", "organization": "org002"},
    {"shop_code": "shop003", "customer": "cus003", "organization": "org003"}
]

"""
005
仓库映射表
"""
# warehouse_list = {源系统店铺代码，目标系统客户代码，目标系统店铺组织代码}
warehouse_list = [
    {"old_warehouse": "1001", "new_warehouse": "CK001", "organization": "org001"},
    {"old_warehouse": "1002", "new_warehouse": "CK002", "organization": "org002"},
    {"old_warehouse": "1003", "new_warehouse": "CK003", "organization": "org003"}
]

"""
006
执行函数
"""
# 后端执行代码
Header_mapping = mapping_list[0]
Details_designate = mapping_list[1]
Details_mapping = mapping_list[2]

# 时间替换函数
def convert_to_yyyy_mm_dd(date_string):
    from datetime import datetime
    date_formats = [
        # 原时间池
        '%Y-%m-%d',  # YYYY-MM-DD
        '%m/%d/%Y',  # MM/DD/YYYY
        '%d-%b-%Y',  # DD-MMM-YYYY
        '%d %B, %Y',  # DD Month, YYYY
        '%Y-%m-%d %H:%M:%S',
        '%Y-%m-%dT%H:%M:%S'  # 金蝶通用格式
    ]

    for date_format in date_formats:
        try:
            date = datetime.strptime(date_string, date_format)
            return date.strftime('%Y-%m-%d')
        except ValueError:
            continue
    return None
    
# 判断映射表目标系统字段后缀函数
def to_format(field_method):
    def wrapper(*args, **kwargs):
        target_field = kwargs.get('target_field')  # 获取target_field参数
        if target_field.endswith("#str#"):
            new_target_field = target_field[:-5]  # 获取正确无后缀的字段名
            target_value = str(field_method(*args, **kwargs))
            dic_target = {new_target_field: target_value}
            return dic_target
        elif target_field.endswith("#int#"):
            new_target_field = target_field[:-5]  # 获取正确无后缀的字段名
            target_value = int(field_method(*args, **kwargs))
            dic_target = {new_target_field: target_value}
            return dic_target
        elif target_field.endswith("#float#"):
            new_target_field = target_field[:-7]  # 获取正确无后缀的字段名
            target_value = float(field_method(*args, **kwargs))
            dic_target = {new_target_field: target_value}
            return dic_target
        elif target_field.endswith("#yyyy-mm-dd#"):
            new_target_field = target_field[:-12]  # 获取正确无后缀的字段名
            target_value = field_method(*args, **kwargs)  # 原来的时间带出来
            new_target_value = convert_to_yyyy_mm_dd(target_value)
            dic_target = {new_target_field: new_target_value}
            return dic_target
        else:  # 不做数据处理
            target_value = field_method(*args, **kwargs)
            dic_target = {target_field: target_value}
            return dic_target

    return wrapper

# 判断映射表源系统字段前缀函数
@to_format
def field_method(source_field, json_obj, item_units_list, json_data=None, target_field=None,
                 target_data=None):  # json_data, target_field, target_data 因为是明细表才需要用的，所以默认是传None
    # 无方法
    if source_field in json_obj:
        return json_obj.get(source_field)
    # 重复方法
    elif source_field.startswith(u"重复_"):
        repeat_value = json_obj.get(source_field.replace(u"重复_", ""))
        return repeat_value
    # 常量方法
    elif source_field.startswith(u"常量_"):
        constant_value = source_field.replace(u"常量_", "")  # 获取正确无前缀的字段名
        return constant_value
    # 源主表
    elif source_field.startswith(u"源主表_"):
        old_Header_value = json_data.get(source_field.replace(u"源主表_", ""))  # json_data是源系统主表
        return old_Header_value
    # 新主表
    elif source_field.startswith(u"新主表_"):
        new_Header_value = target_data.get(source_field.replace(u"新主表_", ""))  # target_data是源系统主表
        return new_Header_value
    # 单位
    elif source_field.startswith(u"单位_"):
        unit_item = json_obj.get(source_field.replace(u"单位_", ""))  # 获取正确无前缀的字段名
        for i in item_units_list:  # 单位列表for循环
            if str(unit_item) == str(i.get("identity")):
                return i.get("unit_id")  # 返回单位ID
    # 店铺映射客户
    elif source_field.startswith(u"店铺映射客户_"):
        shop_code = json_obj.get(source_field.replace(u"店铺映射客户_", ""))  # 获取正确无前缀的字段名
        for i in shop_list:  # 店铺列表for循环
            if str(shop_code) == str(i.get("shop_code")):
                return i.get("customer")  # 返回客户代码
    # 店铺映射组织
    elif source_field.startswith(u"店铺映射组织_"):
        shop_code = json_obj.get(source_field.replace(u"店铺映射组织_", ""))  # 获取正确无前缀的字段名
        for i in shop_list:  # 店铺列表for循环
            if str(shop_code) == str(i.get("shop_code")):
                return i.get("organization")  # 返回组织代码
    # 仓库映射仓库
    elif source_field.startswith(u"仓库映射仓库_"):
        warehouse = json_obj.get(source_field.replace(u"仓库映射仓库_", ""))  # 在明细表获取源系统仓库代码
        for i in warehouse_list:  # 仓库列表for循环
            if str(warehouse) == str(i.get("old_warehouse")):
                return i.get("new_warehouse")  # 返回目标系统仓库代码
    # 仓库映射组织
    elif source_field.startswith(u"仓库映射组织_"):
        warehouse = json_obj.get(source_field.replace(u"仓库映射组织_", ""))  # 在明细表获取源系统仓库代码
        for i in warehouse_list:  # 仓库列表for循环
            if str(warehouse) == str(i.get("old_warehouse")):
                return i.get("organization")  # 返回目标系统仓库组织
    # 主表仓库映射仓库
    elif source_field.startswith(u"主表仓库映射仓库_"):
        warehouse = json_data.get(source_field.replace(u"主表仓库映射仓库_", ""))  # 在主表获取源系统仓库代码
        for i in warehouse_list:  # 仓库列表for循环
            if str(warehouse) == str(i.get("old_warehouse")):
                return i.get("new_warehouse")  # 返回目标系统仓库代码
    # 主表仓库映射组织
    elif source_field.startswith(u"主表仓库映射组织_"):
        warehouse = json_data.get(source_field.replace(u"主表仓库映射组织_", ""))  # 在主表获取源系统仓库代码
        for i in warehouse_list:  # 仓库列表for循环
            if str(warehouse) == str(i.get("old_warehouse")):
                return i.get("organization")  # 返回目标系统仓库代码
    # 算单价
    elif source_field.startswith(u"算单价_"):
        Price_value = source_field.replace(u"算单价_", "").replace("(", "").replace(")", "")  # 获取正确无前缀的字段名,去除左括号，去除右括号
        amount_value, qty_value = Price_value.split("/")
        amount = str(json_obj.get(amount_value))
        qty = str(json_obj.get(qty_value))
        monovalent = float(amount) / int(qty)
        return monovalent
    else:
        str_log = u"源系统映射字段\"{}\"不在源系统json报文中".format(source_field)
        return str_log



# 执行函数
def api_mapping(json_data, Header_mapping, Details_designate, Details_mapping, item_units_list=item_units_list):
    # 创建目标字段映射字典
    target_data = {}

    # 处理主表映射
    for source_field, target_field in Header_mapping.items():  # 遍历映射表的键值
        dic1_target = field_method(target_field=target_field, source_field=source_field, json_obj=json_data,
                                   item_units_list=item_units_list)  # 调用装饰器函数返回字典
        target_data.update(dic1_target)
    # 处理明细表映射
    if Details_designate[0] in json_data:
        # 获取商品明细列表
        source_list = json_data[Details_designate[0]]
        # 创建目标商品明细字段映射列表
        target_detail_list = []
        # 遍历源系统返回的每个json对象
        for json_obj in source_list:
            # 创建目标商品字段映射字典
            mapped_data = {}
            # 根据字段映射规则进行映射
            for source_field, target_field in Details_mapping.items():
                dic2_target = field_method(target_field=target_field, source_field=source_field, json_data=json_data,
                                           json_obj=json_obj, item_units_list=item_units_list,
                                           target_data=target_data)  # 调用装饰器函数返回字典
                mapped_data.update(dic2_target)
            # 将映射后的结果添加到列表中
            target_detail_list.append(mapped_data)
        target_data[Details_designate[1]] = target_detail_list

    # 返回映射后的结果
    return target_data


# 执行代码
target_data = api_mapping(json_data, Header_mapping, Details_designate, Details_mapping)
print("target_data", target_data)
# output：{
#     "target_data":{
#         "target_field999":"源系统映射字段\"source_field999\"不在源系统json报文中",
#         "target_time":"2023-10-29",
#         "target_warehouse":"CK001",
#         "target_shopzuzhi":"org001",
#         "target_field1":"A001",
#         "target_field2":"A002",
#         "target_field3":"A003",
#         "target_key":"123456",
#         "target_field4":"A001",
#         "target_field5":"X001",
#         "target_shop":"cus001",
#         "target_warehousezuzhi":"org001",
#         "target_detils":[
#             {
#                 "target_warehouse":"1001",
#                 "target_warehouse2":"CK001",
#                 "target_units":"1",
#                 "target_qty":2,
#                 "target_field10":"X002",
#                 "target_price":50,
#                 "target_item2":"SP001",
#                 "target_item":"SP001",
#                 "target_warehouse_org":"org001"
#             },
#             {
#                 "target_warehouse":"1001",
#                 "target_warehouse2":"CK001",
#                 "target_units":"2",
#                 "target_qty":3,
#                 "target_field10":"X002",
#                 "target_price":30,
#                 "target_item2":"SP002",
#                 "target_item":"SP002",
#                 "target_warehouse_org":"org001"
#             }
#         ]
#     }
# }